import axios, { AxiosRequestConfig } from "axios";
import macConfig from "@/config/config";
import { ElNotification } from "element-plus";
import storage from "@/utils/storage";
import bus from "vue3-eventbus";
import eventKey from "@/const/busEventConstKey";
// import { AdminResultObject } from "./models";

const accessTokenKey = "access-token";
const refreshAccessTokenKey = `x-${accessTokenKey}`;
// 清除 token
const clearAccessTokens = () => {
  storage.clearItem(accessTokenKey);
  storage.clearItem(refreshAccessTokenKey);
  // window.location.reload();
};

// 创建axios的实例
const service = axios.create({
  baseURL: macConfig.apiBaseUrl,
  timeout: 10000,
});

service.interceptors.request.use(
  (config) => {
    if (config.responseType?.toString() == "application/octet-stream") {
      config.timeout = 0;
    }
    const accessToken = storage.getItem(accessTokenKey);
    if (accessToken) {
      // 将 token 添加到请求报文头中
      config.headers!["Authorization"] = `Bearer ${accessToken}`;

      // 判断 accessToken 是否过期
      const jwt: any = decryptJWT(accessToken);
      const exp = getJWTDate(jwt.exp as number);

      // token 已经过期
      if (new Date() >= exp) {
        // 获取刷新 token
        const refreshAccessToken = storage.getItem(refreshAccessTokenKey);
        // 携带刷新 token
        if (refreshAccessToken) {
          config.headers!["X-Authorization"] = `Bearer ${refreshAccessToken}`;
        }
      }
    }
    return config;
  },
  (error) => {
    // 处理请求错误
    if (error.request) {
      console.log(error);
    }

    return Promise.reject(error);
  }
);
service.interceptors.response.use(
  (response) => {
    // 获取状态码和返回数据
    var status = response.status;
    var serve = response.data;

    // 处理 401
    if (status === 401) {
      clearAccessTokens();

      bus.emit(eventKey.needLogin);
    }

    // 处理未进行规范化处理的
    if (status >= 400) {
      throw new Error(response.statusText || "Request Error.");
    }

    // 处理规范化结果错误
    if (serve && serve.hasOwnProperty("errors") && serve.errors) {
      throw new Error(JSON.stringify(serve.errors || "Request Error."));
    }

    // 读取响应报文头 token 信息
    var accessToken = response.headers[accessTokenKey];
    var refreshAccessToken = response.headers[refreshAccessTokenKey];

    // 判断是否是无效 token
    if (accessToken === "invalid_token") {
      clearAccessTokens();
    } else if (
      refreshAccessToken &&
      accessToken &&
      accessToken !== "invalid_token"
    ) {
      storage.setItem(accessTokenKey, accessToken);
      storage.setItem(refreshAccessTokenKey, refreshAccessToken);
    }

    if (response.headers["content-type"] == "application/octet-stream") {
      //文件流
      return response.data;
    }

    switch (response.data.code) {
      case 500:
        ElNotification({
          title: "错误",
          message: response.data.message,
          type: "error",
          // duration: 0,
          // zIndex: 1000,
          showClose: false,
        });
        return Promise.reject(response.data);
      default:
        break;
    }

    return response.data.result;
  },
  (error) => {
    switch (error.response?.status) {
      case 401:
        // console.log("无权访问")
        clearAccessTokens();
        bus.emit(eventKey.needLogin);

        // router.push({ path: '/login' })
        break;
      case 403:
        console.log("token过期啦");
        // router.push({path: '/login'})
        break;
      case 404:
        console.log("404啦");
        // router.push({path: '/404'})
        break;
      case 500:
        console.log("500啦");
        // router.push({path: '/404'})
        break;
      default:
        return Promise.reject(error);
    }
    return Promise.reject(error);
  }
);

async function get<T>(
  url: string,
  params?: object,
  config?: AxiosRequestConfig
) {
  const response = await service.get<T>(url, { params, ...config });
  return response as T;
}

async function post<T>(
  url: string,
  data?: object,
  config?: AxiosRequestConfig
) {
  const response = await service.post<T>(url, { ...data, ...config });
  return response as T;
}
const request = { get, post };
export { request };

// export function request<T>(config: AxiosRequestConfig) {
//   // 创建axios的实例
//   const instance = axios.create({
//     baseURL: macConfig.apiBaseUrl,
//     timeout: 10000,
//   });
//   // 请求拦截器配置
//   instance.interceptors.request.use(
//     (config) => {
//       if (config.responseType?.toString() == "application/octet-stream") {
//         config.timeout = 0;
//       }
//       const accessToken = storage.getItem(accessTokenKey);
//       if (accessToken) {
//         // 将 token 添加到请求报文头中
//         config.headers!["Authorization"] = `Bearer ${accessToken}`;

//         // 判断 accessToken 是否过期
//         const jwt: any = decryptJWT(accessToken);
//         const exp = getJWTDate(jwt.exp as number);

//         // token 已经过期
//         if (new Date() >= exp) {
//           // 获取刷新 token
//           const refreshAccessToken = storage.getItem(refreshAccessTokenKey);
//           // 携带刷新 token
//           if (refreshAccessToken) {
//             config.headers!["X-Authorization"] = `Bearer ${refreshAccessToken}`;
//           }
//         }
//       }
//       return config;
//     },
//     (error) => {
//       // 处理请求错误
//       if (error.request) {
//         console.log(error);
//       }

//       return Promise.reject(error);
//     }
//   );
//   // 响应拦截器配置
//   instance.interceptors.response.use(
//     (response) => {
//       // 获取状态码和返回数据
//       var status = response.status;
//       var serve = response.data;

//       // 处理 401
//       if (status === 401) {
//         clearAccessTokens();
//       }

//       // 处理未进行规范化处理的
//       if (status >= 400) {
//         throw new Error(response.statusText || "Request Error.");
//       }

//       // 处理规范化结果错误
//       if (serve && serve.hasOwnProperty("errors") && serve.errors) {
//         throw new Error(JSON.stringify(serve.errors || "Request Error."));
//       }

//       // 读取响应报文头 token 信息
//       var accessToken = response.headers[accessTokenKey];
//       var refreshAccessToken = response.headers[refreshAccessTokenKey];

//       // 判断是否是无效 token
//       if (accessToken === "invalid_token") {
//         clearAccessTokens();
//       } else if (
//         refreshAccessToken &&
//         accessToken &&
//         accessToken !== "invalid_token"
//       ) {
//         storage.setItem(accessTokenKey, accessToken);
//         storage.setItem(refreshAccessTokenKey, refreshAccessToken);
//       }

//       if (response.headers["content-type"] == "application/octet-stream") {
//         //文件流
//         return response.data;
//       }

//       switch (response.data.code) {
//         case 500:
//           ElNotification({
//             title: "错误",
//             message: response.data.message,
//             type: "error",
//             // duration: 0,
//             // zIndex: 1000,
//             showClose: false,
//             customClass: "glass-notify",
//           });
//           return Promise.reject(response.data);
//         default:
//           break;
//       }

//       return response.data.result;
//     },
//     (error) => {
//       switch (error.response.status) {
//         case 401:
//           // console.log("无权访问")
//           clearAccessTokens();
//           bus.emit(eventKey.needLogin);

//           // router.push({ path: '/login' })
//           break;
//         case 403:
//           console.log("token过期啦");
//           // router.push({path: '/login'})
//           break;
//         case 404:
//           console.log("404啦");
//           // router.push({path: '/404'})
//           break;
//         case 500:
//           console.log("500啦");
//           // router.push({path: '/404'})
//           break;
//         default:
//           return Promise.reject(error);
//       }
//       return Promise.reject(error);
//     }
//   );
//   // 发送真正的网络请求
//   return instance(config);
// }

/**
 * 解密 JWT token 的信息
 * @param token jwt token 字符串
 * @returns <any>object
 */
export function decryptJWT(token: string): any {
  token = token.replace(/_/g, "/").replace(/-/g, "+");
  var json = decodeURIComponent(escape(window.atob(token.split(".")[1])));
  return JSON.parse(json);
}

/**
 * 将 JWT 时间戳转换成 Date
 * @description 主要针对 `exp`，`iat`，`nbf`
 * @param timestamp 时间戳
 * @returns Date 对象
 */
export function getJWTDate(timestamp: number): Date {
  return new Date(timestamp * 1000);
}

// export default request;
